/*
 ============================================================================
 Name        : sobrecarga.c
 Author      : 
 Version     :
 Copyright   : Your copyright notice
 Description : Hello World in C, Ansi-style
 ============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdarg.h>
#include <sys/resource.h>
#include <pthread.h>
#include <time.h>

/* Private variables ---------------------------------------------------------*/
static int 		ttyS0_fd;					/*!< Control file descriptor */
static int 		ttyS1_fd;					/*!< Data file descriptor */
static struct 	termios tio;				/*!< Termios struct */

pthread_t thread_serial0, thread_serial1;

time_t t;
struct tm *tm;
FILE *fp;

/* serial */
int aux_USART0_open();
int aux_USART1_open();
void aux_USART0_putc(const char *s, int len);
int aux_USART0_puts(const char *format, ...);
int aux_USART1_puts(const char *format, ...);
int aux_USART0_gets(char *s);
int aux_USART1_gets(char *s);

void *serial_0(void *threadid);
void *serial_1(void *threadid);

#define SERIAL_DADOS 	"/dev/ttyUSB0"  // Serial do console
#define SERIAL_CONTROLE "/dev/ttyUSB1"

int main(void)
{
	int i;
	char temp_buf[255];
	char file_name[255];
	char buf_tx[300];

	aux_USART0_open(B57600);
	aux_USART1_open(B57600);

	/* Espera o sistema ficar pronto */
	do
	{
		bzero(temp_buf, sizeof(temp_buf));
		if(aux_USART1_gets(temp_buf)>0)
			printf("%s\r\n", temp_buf);
	}while(strcmp(temp_buf, "procd: - init complete -") != 0);

	/* Inicia a aplicação */
	aux_USART1_puts("\n");
	aux_USART1_puts("/bin/exatron\n");

	/* Limpa serial */
	tcflush(ttyS0_fd, TCIOFLUSH);
	tcflush(ttyS1_fd, TCIOFLUSH);

	/* Pega Start */
	bzero(temp_buf, sizeof(temp_buf));
	while(aux_USART0_gets(temp_buf) == 0);
	printf("%s\r\n", temp_buf);

	/* Pega Rede */
	bzero(temp_buf, sizeof(temp_buf));
	while(aux_USART0_gets(temp_buf) == 0);
	printf("%s\r\n", temp_buf);

	sleep(20);

	/* Espera Conectar */
	do
	{
		tcflush(ttyS0_fd, TCIOFLUSH);
		aux_USART0_puts("5\r\n");
		sleep(2);
		bzero(temp_buf, sizeof(temp_buf));
		aux_USART0_gets(temp_buf);
		printf("%s\r\n", temp_buf);
	}while(strcmp(temp_buf, "WF_CST=0") != 0);

	do
	{
		/* Abre socket server TCP */
		tcflush(ttyS0_fd, TCIOFLUSH);
		aux_USART0_puts("20=5000\r\n");
		sleep(5);
		bzero(temp_buf, sizeof(temp_buf));
		while(aux_USART0_gets(temp_buf) == 0);
		printf("%s\r\n", temp_buf);
	}while(strcmp(temp_buf, "TCP_OPS=0;0") != 0);

	do
	{
		/* Abre socket server UDP */
		tcflush(ttyS0_fd, TCIOFLUSH);
		aux_USART0_puts("22=4000\r\n");
		sleep(5);
		bzero(temp_buf, sizeof(temp_buf));
		while(aux_USART0_gets(temp_buf) == 0);
		printf("%s\r\n", temp_buf);
	}while(strcmp(temp_buf, "UDP_OPS=1;0") != 0);

	/* Abre arquivo de log */
	bzero(file_name, sizeof(file_name));

	t = time(NULL);
	tm = localtime(&t);

	sprintf(file_name, "/home/ubuntu/Log_%d-%d-%d_%d-%d.txt", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min);
	fp = fopen(file_name, "w");
	if(!fp)
		printf("Erro ao criar arquivo de log!\r\n");
	else
		printf("Arquivo de log: %s\r\n", file_name);

	/* Threads que ficam recebendo */
	pthread_create(&thread_serial0, NULL, serial_0, NULL);
	pthread_create(&thread_serial1, NULL, serial_1, NULL);

	memset(buf_tx, 'B', sizeof(buf_tx));

	/* Pede comandos */
	while(1)
	{
		for(i=4;i<15;i++)
		{
			/* Se não tiver um delay entre os comandos, o modulo sempre ira
			 * pegar só o primeiro, pois recebe o primeiro e leva um tempo
			 * para executar, dai descarta os outros.
			 */

			//aux_USART0_puts("1\r\n"); 			// Pede IP
			usleep(20000); // 20ms
			aux_USART0_puts("SCK_IRDR=%d\r\n", i);	// Pede IRDR
			usleep(20000); // 20ms
			aux_USART0_puts("SCK_IRDR2\r\n"); 			// Pede IRDR2
			usleep(20000); // 20ms
			aux_USART0_puts("SCK_RXD=%d\r\n", i); 	// Pede RXD
			usleep(20000); // 20ms
			aux_USART0_puts("SCK_ITDR=%d\r\n", i); 	// Pede ITDR
			usleep(20000); // 20ms
			aux_USART0_puts("SCK_TXD=%d;300\r\n", i); // Pede TXD
			usleep(20000); // 20ms
			aux_USART1_puts(buf_tx); 			// Envia TXD
			usleep(50000); // 50ms
			aux_USART0_puts("SCK_GSS=%d\r\n", i); 	// Pede GSS
			usleep(20000); // 20ms
		}
	}

	return EXIT_SUCCESS;
}

void *serial_0(void *threadid)
{
	char buffer[4000];
	char buffer_file[4000];

	bzero(buffer, sizeof(buffer));
	bzero(buffer_file, sizeof(buffer_file));

	while(1)
	{
		tcflush(ttyS0_fd, TCIFLUSH);
		if(aux_USART0_gets(buffer) > 0)
		{
			printf("%s\r\n", buffer);
			t = time(NULL);
			tm = localtime(&t);
			sprintf(buffer_file, "Serial comando: %d:%d:%d - %s\n", tm->tm_hour, tm->tm_min, tm->tm_sec, buffer);
			fputs(buffer_file, fp);
			bzero(buffer, sizeof(buffer));
			bzero(buffer_file, sizeof(buffer_file));
			usleep(1000);
		}
	}
}

void *serial_1(void *threadid)
{
	char buffer[4000];

	bzero(buffer, sizeof(buffer));

	while(1)
	{
		tcflush(ttyS1_fd, TCIFLUSH);
		if(aux_USART1_gets(buffer) > 0)
		{
			printf("%s\r\n", buffer);
			bzero(buffer, sizeof(buffer));
			usleep(1000);
		}
	}
}


/**
  * @brief  Abre a porta serial ttyS0 Controle.
  * @param  Nenhum
  * @retval Nenhum
  */
int aux_USART0_open(int baud)
{
    bzero(&tio,sizeof(tio));
    tio.c_iflag = 0;
    tio.c_oflag = 0;
    tio.c_cflag = CS8|CREAD|CLOCAL; // 8n1
    tio.c_lflag = 0;
    tio.c_cc[VMIN] = 0;
    tio.c_cc[VTIME] = 10;

    //ttyS0_fd = open("/dev/ttyS0", O_RDWR | O_NONBLOCK);
    ttyS0_fd = open(SERIAL_CONTROLE, O_RDWR);
    if(ttyS0_fd == -1)
    	return EXIT_FAILURE;
    cfsetospeed(&tio, baud);
    cfsetispeed(&tio, baud);
    tcsetattr(ttyS0_fd,TCSANOW,&tio);

    return EXIT_SUCCESS;
}

/**
  * @brief  Abre a porta serial ttyS1 Dados.
  * @param  Nenhum
  * @retval Nenhum
  */
int aux_USART1_open(int baud)
{
    bzero(&tio,sizeof(tio));
    tio.c_iflag = 0;
    tio.c_oflag = 0;
    tio.c_cflag = CS8|CREAD|CLOCAL; // 8n1
    tio.c_lflag = 0;
    tio.c_cc[VMIN] = 0;
    tio.c_cc[VTIME] = 1;

    //ttyS1_fd = open("/dev/ttyS1", O_RDWR | O_NONBLOCK);
    ttyS1_fd = open(SERIAL_DADOS, O_RDWR);
    if(ttyS1_fd == -1)
    	return EXIT_FAILURE;
    cfsetospeed(&tio, baud);
    cfsetispeed(&tio, baud);
    tcsetattr(ttyS1_fd,TCSANOW,&tio);

    return EXIT_SUCCESS;
}

/**
  * @brief  Envia string, termina no '\0'.
  * @param  char *format, ...: Formato e variáveis
  * @retval Nenhum
  */

void aux_USART0_putc(const char *s, int len)
{
	int n = 0;
	int nrec = 0;
	do
	{
		nrec = write(ttyS0_fd, s+n, len-n);
		n += nrec;
	}while(n < len && nrec > 0);
}

int aux_USART0_puts(const char *format, ...)
{
	int n = 0;
	int nrec = 0;
	static char buf[4096];
	va_list args;

	bzero(buf, sizeof(buf));

	va_start(args, format);
	vsprintf(buf, format, args);
	va_end(args);

	do
	{
		nrec = write(ttyS0_fd, buf+n, strlen(buf)-n);
		n += nrec;
	}while(n < strlen(buf) && nrec > 0);

	return n;
}

/**
  * @brief  Envia string, termina no '\0'.
  * @param  char *format, ...: Formato e variáveis
  * @retval Nenhum
  */
int aux_USART1_puts(const char *format, ...)
{
	int n = 0;
	int nrec = 0;
	static char buf[4096];
	va_list args;

	bzero(buf, sizeof(buf));

	va_start(args, format);
	vsprintf(buf, format, args);
	va_end(args);

	do
	{
		nrec = write(ttyS1_fd, buf+n, strlen(buf)-n);
		n += nrec;
	}while(n < strlen(buf) && nrec > 0);

	return n;
}

/**
  * @brief  Lê dados da serial, termina no '\n' ou '\r' ou '\0' exclusivo.
  * @param  char *s: Ponteiro para string de retorno
  * @retval int: Número de bytes lidos
  */
int aux_USART0_gets(char *s)
{
	int i = 0;
	int n = 0;
	int nrec = 0;
	int cont = 0;
	char buf[1024];
	int isexit = 0;

	memset(buf, 0, sizeof(buf));

	do
	{
		nrec = read(ttyS0_fd, buf+n, 1024-n);

		n += nrec;
		i = cont;

		do
		{
			/* Se caracter válido */
			if(buf[i] != '\r' && buf[i] != '\n' && nrec > 0)
			{
				memcpy(&s[i], &buf[i], 1);
				cont++;
			}
			else
			{
				isexit = 1;
			}
			i++;
		}while(i < n && isexit == 0);

	}while((isexit == 0));

	return cont;
}

/**
  * @brief  Lê dados da serial, termina no '\n' ou '\r' ou '\0' exclusivo.
  * @param  char *s: Ponteiro para string de retorno
  * @retval int: Número de bytes lidos
  */
int aux_USART1_gets(char *s)
{
	int i = 0;
	int n = 0;
	int nrec = 0;
	int cont = 0;
	char buf[1024];
	int isexit = 0;

	memset(buf, 0, sizeof(buf));

	do
	{
		nrec = read(ttyS1_fd, buf+n, 1024-n);

		n += nrec;
		i = cont;

		do
		{
			/* Se caracter válido */
			if(buf[i] != '\r' && buf[i] != '\n' && nrec > 0)
			{
				memcpy(s++, &buf[i], 1);
				cont++;
			}
			else
			{
				isexit = 1;
			}
			i++;
		}while(i < n && isexit == 0);

	}while((isexit == 0) && n < 300);

	return cont;
}
